﻿using EasyIot.Common;
using DotNetty.Buffers;
using DotNetty.Common.Utilities;
using DotNetty.Transport.Channels;
using DotNettyExtensions;
using System;
using System.Text;
using System.Net;
using DotNettyExtensions.entity;

namespace EasyIot.WebApi.Utility
{
    public class ClientProtocol : IProtocolHandler
    {
        public const int HEAD1 = 0x49;// I
        public const int HEAD2 = 0x4F;// O
        public const int HEAD3 = 0x54;// T
        public const int HEAD4 = 0x3D;// =
        public const string HEAD = "IOT=";
        public const char SPLIT1 = '&';
        public const char SPLIT2 = '#';

        public void ChannelRead(IChannelHandlerContext ctx, EndPoint remote, object msg)
        {
            if (!ctx.Channel.Active) return;

            string data_content = "";

            try
            {
                string sn = ServerMgr.GetSN(remote);
                UidEntity uidEntity = ServerMgr.GetUid(sn);
                string uid = "";

                if (null != uidEntity)
                {
                    uid = uidEntity.Uid; 
                }

                if (!ServerMgr.dicSn2Buffer.ContainsKey(sn)) ServerMgr.dicSn2Buffer.TryAdd(sn, Unpooled.Buffer(1024));
                IByteBuffer oldBuffer = ServerMgr.dicSn2Buffer[sn];

                if (null != msg)
                {
                    IByteBuffer recvBuffer = (IByteBuffer)msg;
                    int size = recvBuffer.ReadableBytes;
                    if (size > 0)
                    {
                        //recvBuffer.markReaderIndex();
                        oldBuffer.WriteBytes(recvBuffer);
                        //ReferenceCountUtil.Release(recvBuffer);
                        //
                        //recvBuffer.resetReaderIndex();
                        //byte[] recv = new byte[size];
                        //recvBuffer.readBytes(recv);
                        //CTxtHelp.AppendLog("接收数据：" + CDataHelper.ArrayByteToString(recv));
                    }
                }

                byte head1 = 0; byte head2 = 0; byte head3 = 0; byte head4 = 0; bool headok = false;

                oldBuffer.MarkReaderIndex();

                while (oldBuffer.IsReadable())
                {
                    head1 = oldBuffer.ReadByte();
                    if (HEAD1 == head1)// 垃圾包处理
                    {
                        head2 = oldBuffer.ReadByte(); if (!oldBuffer.IsReadable()) { oldBuffer.ResetReaderIndex(); return; }
                        head3 = oldBuffer.ReadByte(); if (!oldBuffer.IsReadable()) { oldBuffer.ResetReaderIndex(); return; }
                        head4 = oldBuffer.ReadByte(); if (!oldBuffer.IsReadable()) { oldBuffer.ResetReaderIndex(); return; }

                        if (HEAD2 == head2 && HEAD3 == head3 && HEAD4 == head4)
                        {
                            headok = true;
                            break;
                        }

                        break;
                    }
                    else
                    {
                        oldBuffer.MarkReaderIndex();
                        Logger.Error("Error,Unable to parse the data：" + head1 + " source:" + (string.IsNullOrEmpty(uid) ? sn : uid));
                    }
                }

                if (!oldBuffer.IsReadable())
                {
                    if (headok) oldBuffer.ResetReaderIndex();
                    return;
                }

                byte[] arrlen = new byte[4]; oldBuffer.ReadBytes(arrlen); if (!oldBuffer.IsReadable()) { oldBuffer.ResetReaderIndex(); return; }
                int len = CommonUtility.String2Int(CommonUtility.ByteToString(arrlen)); if (-1 == len) return; if (ServerMgr.GetWaitRecvRemain(oldBuffer, len)) { oldBuffer.ResetReaderIndex(); return; }
                byte[] source = new byte[len]; oldBuffer.ReadBytes(source);

                string data = CommonUtility.ByteToString(source);
                if (null == data || 0 == data.Length || data.Length - 1 != data.LastIndexOf(SPLIT1))
                {
                    return;
                }
                data = data.Substring(1, data.Length - 2);
                string[] item = data.Split(SPLIT1);
                if (null == item || 4 != item.Length)
                {
                    return;
                }

                uid = item[0];
                string taskid = item[1];
                int cmd = CommonUtility.String2Int(item[2]);
                string content = item[3];

                //Program.AddMessage("R: [" + sn + "] cmd=" + cmd.ToString() + " data=" + data);

                switch (cmd)
                {
                    case 1:
                        ServerMgr.AddUid(sn, uid, ctx, remote);
                        Logger.Info("心跳反馈,uid=" + uid);
                        ProtocolBase.SendProtocol(ctx, remote, uid, cmd, "ok");
                        break;
                    case 2:
                        //analysis.Msg = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                        break;
                    case 3:
                        // 数据透传
                        break;
                }

                if (!oldBuffer.IsReadable())
                {
                    oldBuffer.Clear();
                }
                else
                {
                    ChannelRead(ctx, remote, null);// 处理粘包
                }
            }
            catch (Exception ex)
            {
                Logger.Error("[Error] ClientProtocol_ChannelRead,data_content=" + data_content + ",errmsg=" + ex.Message);
            }
        }

        string GetProtocol(string uid, string taskId, int cmd, string msg)
        {
            string content = SPLIT1 + uid + SPLIT1 +
                            taskId + SPLIT1 +
                            CommonUtility.Lpad(cmd, 2) + SPLIT1 +
                            msg + SPLIT1;
            StringBuilder data = new StringBuilder();
            data.Append(HEAD);
            data.Append(CommonUtility.Lpad(CommonUtility.GetLength(content), 4));
            data.Append(content);
            return data.ToString();
        } 
    }
}